package com.solution.common.codegen;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

import com.alibaba.fastjson.JSONObject;
import com.mysql.jdbc.PreparedStatement;
import com.solution.common.config.PublicConfigUtil;
import com.solution.common.utils.string.StringUtil;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class CodeBuilder {

	private DatabaseMetaData dbMetaData = null;
	private Connection con = null;

	public CodeBuilder() {
		this.getDatabaseMetaData();
	}

	private void getDatabaseMetaData() {
		try {
			if (dbMetaData == null) {
				
				Class.forName(PublicConfigUtil.readConfig("jdbc.driverClassName"));
				String url = PublicConfigUtil.readConfig("jx.jdbc.url");
				String user = PublicConfigUtil.readConfig("jx.jdbc.username");
				String password = PublicConfigUtil.readConfig("jx.jdbc.password");
				con = DriverManager.getConnection(url, user, password);
				dbMetaData = con.getMetaData();
				
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取连接
	 * @return
	 */
	private Connection getDbConnection(){
		Connection conn = null;
		try {
			Class.forName(PublicConfigUtil.readConfig("jdbc.driverClassName"));
			String url = PublicConfigUtil.readConfig("jx.jdbc.url");
			String user = PublicConfigUtil.readConfig("jx.jdbc.username");
			String password = PublicConfigUtil.readConfig("jx.jdbc.password");
			conn = DriverManager.getConnection(url, user, password);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return conn;
	}

	/**
	 * 获得数据库的一些相关信息
	 */
	public void getDataBaseInformations() {
		try {
			System.out.println("数据库已知的用户: " + dbMetaData.getUserName());
			System.out.println("数据库的系统函数的逗号分隔列表: "
					+ dbMetaData.getSystemFunctions());
			System.out.println("数据库的时间和日期函数的逗号分隔列表: "
					+ dbMetaData.getTimeDateFunctions());
			System.out.println("数据库的字符串函数的逗号分隔列表: "
					+ dbMetaData.getStringFunctions());
			System.out.println("数据库供应商用于 'schema' 的首选术语: "
					+ dbMetaData.getSchemaTerm());
			System.out.println("数据库URL: " + dbMetaData.getURL());
			System.out.println("是否允许只读:" + dbMetaData.isReadOnly());
			System.out.println("数据库的产品名称:"
					+ dbMetaData.getDatabaseProductName());
			System.out.println("数据库的版本:"
					+ dbMetaData.getDatabaseProductVersion());
			System.out.println("驱动程序的名称:" + dbMetaData.getDriverName());
			System.out.println("驱动程序的版本:" + dbMetaData.getDriverVersion());

			System.out.println();
			System.out.println("数据库中使用的表类型");
			ResultSet rs = dbMetaData.getTableTypes();
			while (rs.next()) {
				System.out.println(rs.getString(1));
			}
			rs.close();
			System.out.println();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 获得该用户下面的所有表
	 */
	public String getTableComment(String tableName) {
		String comment = "";
		try {
			// table type. Typical types are "TABLE", "VIEW", "SYSTEM TABLE",
			// "GLOBAL TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
			String[] types = { "TABLE" };
			ResultSet rs = dbMetaData.getTables(null, "%", tableName, types);
			while (rs.next()) {
				comment = rs.getString("REMARKS"); // 表备注
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return comment;
	}
	

	/**
	 * 获得该用户下面的所有表
	 */
	public List<String[]> getAllTableList(String schemaName) {
		List<String[]> resultList = new ArrayList<String[]>();
		try {
			// table type. Typical types are "TABLE", "VIEW", "SYSTEM TABLE",
			// "GLOBAL TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
			String[] types = { "TABLE" };
			ResultSet rs = dbMetaData.getTables(null, schemaName, "%", types);
			while (rs.next()) {
				String tableName = rs.getString("TABLE_NAME"); // 表名
				String tableType = rs.getString("TABLE_TYPE"); // 表类型
				String remarks = rs.getString("REMARKS"); // 表备注
				System.out.println(tableName + "-" + tableType + "-" + remarks);
				resultList.add(new String[]{tableName.toUpperCase(),tableName+"("+remarks.split("\\|")[0]+")"});
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return resultList;
	}

	/**
	 * 获得该用户下面的所有视图
	 */
	public void getAllViewList(String schemaName) {
		try {
			String[] types = { "VIEW" };
			ResultSet rs = dbMetaData.getTables(null, schemaName, "%", types);
			while (rs.next()) {
				String viewName = rs.getString("TABLE_NAME"); // 视图名
				String viewType = rs.getString("TABLE_TYPE"); // 视图类型
				String remarks = rs.getString("REMARKS"); // 视图备注
				System.out.println(viewName + "-" + viewType + "-" + remarks);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获得数据库中所有方案名称
	 */
	public void getAllSchemas() {
		try {
			ResultSet rs = dbMetaData.getSchemas();
			while (rs.next()) {
				String tableSchem = rs.getString("TABLE_SCHEM");
				System.out.println(tableSchem);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
    
    /**
     * 根据数据库字段类型映射成字段类型名称，如是：93 - TIMESTAMP
     * @param cb
     * @return
     */
	public static String getDataTypeName(ColBean cb){
		int dataType = Integer.parseInt(cb.getColType());
		String dataTypeName ="";
		switch(dataType){
			case Types.SMALLINT:{
				dataTypeName="SMALLINT";
				break;
			}
			case Types.INTEGER:{
				dataTypeName="INTEGER";
				break;
			}
			case Types.BIGINT:{
				dataTypeName="BIGINT";
				break;
			}
			case Types.DECIMAL:{
				dataTypeName="DECIMAL("+cb.getColSize()+","+cb.getDecision()+")";
				break;
			}
			case Types.CHAR:{
				dataTypeName="CHAR("+cb.getColSize()+")";
				break;
			}
			case Types.VARCHAR:{
				dataTypeName="VARCHAR("+cb.getColSize()+")";
				break;
			}
			case Types.DATE:{
				dataTypeName="DATE";
				break;
			}
			case Types.TIMESTAMP:{
				dataTypeName="DATETIME";
				break;
			}
			default:{
				throw new RuntimeException("数据库使用的字段类型不规范，请重新检查！");
			}
		
		};
		return dataTypeName;
	}
	
	/**
	 * 更新表的注释字段
	 * @param tableName
	 * @param cbList
	 */
	public void updateTableComment(String tableName,List<ColBean> cbList){
		Connection conn = getDbConnection();
		String sql ="";
		try {
			PreparedStatement pst =null;
			for(ColBean cb : cbList){
				sql = "alter table "+tableName+" modify column "+cb.getColName()+" "+getDataTypeName(cb)+("0".equals(cb.getNullFlag())?" not null":" ")+" comment '"+cb.getColComName()+"'";
				pst = (PreparedStatement) conn.prepareStatement(sql);
				pst.execute();
			}
			pst.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获得表或视图中的所有列信息
	 */
	public List<ColBean> getTableColumns(String schemaName, String tableName) {
		List<ColBean> colbeanList = new ArrayList<ColBean>();
		try {
			ResultSet rs = dbMetaData.getColumns(null, schemaName, tableName,
					"%");
			while (rs.next()) {
				String tableCat = rs.getString("TABLE_CAT");// 表目录（可能为空）
				String tableSchemaName = rs.getString("TABLE_SCHEM");// 表的架构（可能为空）
				String tableName_ = rs.getString("TABLE_NAME");// 表名
				String columnName = rs.getString("COLUMN_NAME");// 列名
				int dataType = rs.getInt("DATA_TYPE"); // 对应的java.sql.Types类型
				String dataTypeName = rs.getString("TYPE_NAME");// java.sql.Types类型
																// 名称
				int columnSize = rs.getInt("COLUMN_SIZE");// 列大小
				int decimalDigits = rs.getInt("DECIMAL_DIGITS");// 小数位数
				int numPrecRadix = rs.getInt("NUM_PREC_RADIX");// 基数（通常是10或2）
				int nullAble = rs.getInt("NULLABLE");// 是否允许为null
				String remarks = rs.getString("REMARKS");// 列描述
				String columnDef = rs.getString("COLUMN_DEF");// 默认值
				int sqlDataType = rs.getInt("SQL_DATA_TYPE");// sql数据类型
				int sqlDatetimeSub = rs.getInt("SQL_DATETIME_SUB"); // SQL日期时间分?
				int charOctetLength = rs.getInt("CHAR_OCTET_LENGTH"); // char类型的列中的最大字节数
				int ordinalPosition = rs.getInt("ORDINAL_POSITION"); // 表中列的索引（从1开始）

				/**
				 * ISO规则用来确定某一列的为空性。 是---如果该参数可以包括空值; 无---如果参数不能包含空值
				 * 空字符串---如果参数为空性是未知的
				 */
				String isNullAble = rs.getString("IS_NULLABLE");

				/**
				 * 指示此列是否是自动递增 是---如果该列是自动递增 无---如果不是自动递增列 空字串---如果不能确定它是否
				 * 列是自动递增的参数是未知
				 */
				String isAutoincrement = rs.getString("IS_AUTOINCREMENT");

				System.out.println(tableCat + "-" + tableSchemaName + "-"
						+ tableName_ + "-" + columnName + "-" + dataType + "-"
						+ dataTypeName + "-" + columnSize + "-" + decimalDigits
						+ "-" + numPrecRadix + "-" + nullAble + "-" + remarks
						+ "-" + columnDef + "-" + sqlDataType + "-"
						+ sqlDatetimeSub + charOctetLength + "-"
						+ ordinalPosition + "-" + isNullAble + "-"
						+ isAutoincrement + "-");
				
				
				// 元数据
				ColBean bean = new ColBean();
				// 列集合
				String[] arg = (columnName.toLowerCase())
						.split("_", 0);
				String colName = "";
				for (int i = 0; i < arg.length; i++) {
					if (i == 0) {
						colName = colName + arg[i];
					} else {
						colName = colName
								+ (arg[i].substring(0, 1)).toUpperCase()
								+ arg[i].substring(1);
					}
				}
				// 首字母小写属性名  驼峰命名法  如：firstName
				bean.setPropertyName(colName);
				
				// 首字符大写的属性名,如：FirstName
				bean.setBpropertyName(colName.substring(0,1).toUpperCase()+colName.substring(1));
				
				// 列名(原始列名大写)
				bean.setColName(columnName.toUpperCase());
				// 首字母大写列名
				bean.setColUppName((colName.substring(0, 1)).toUpperCase()
						+ colName.substring(1));
				// 列注释
				String[] arrs = remarks.split("\\|");
				String colComments = arrs[0];
				if(arrs.length>1){
					// 筛选条件
					String[] condDefArr  = arrs[1].trim().split("#");
					
					if(condDefArr.length==6){
						bean.setCondition(condDefArr[0].toLowerCase());
						bean.setConditionType(condDefArr[1].toLowerCase());
						bean.setShowList(condDefArr[2].toLowerCase());
						bean.setShowForm(condDefArr[3].toLowerCase());
						bean.setInsertDefault(condDefArr[4].toLowerCase());
						bean.setControllerDefault(condDefArr[5]);
					}else{
						// 表格首次没有备注信息进行补充
						// 是否查询条件#显示条件类型#是否在列表中显示#是否在编辑页面显示#在insert语句中使用默认值#在controller中使用默认值设置
						for (ColBean colBean : colbeanList) {
							colBean.setCondition(StringUtil.isEmpty(colBean.getCondition())?"n":colBean.getCondition());
							colBean.setConditionType(StringUtil.isEmpty(colBean.getConditionType())?"n":colBean.getConditionType());
							colBean.setShowList(StringUtil.isEmpty(colBean.getShowList())?"n":colBean.getShowList());
							colBean.setShowForm(StringUtil.isEmpty(colBean.getShowForm())?"y":colBean.getShowForm());
							colBean.setInsertDefault(StringUtil.isEmpty(colBean.getInsertDefault())?"ng":colBean.getInsertDefault());
							colBean.setControllerDefault(StringUtil.isEmpty(colBean.getControllerDefault())?"ng":colBean.getControllerDefault());
						}
					}
				}else{
					// 表格首次没有备注信息进行补充
					// 是否查询条件#显示条件类型#是否在列表中显示#是否在编辑页面显示#在insert语句中使用默认值#在controller中使用默认值设置
					for (ColBean colBean : colbeanList) {
						colBean.setCondition(StringUtil.isEmpty(colBean.getCondition())?"n":colBean.getCondition());
						colBean.setConditionType(StringUtil.isEmpty(colBean.getConditionType())?"n":colBean.getConditionType());
						colBean.setShowList(StringUtil.isEmpty(colBean.getShowList())?"n":colBean.getShowList());
						colBean.setShowForm(StringUtil.isEmpty(colBean.getShowForm())?"y":colBean.getShowForm());
						colBean.setInsertDefault(StringUtil.isEmpty(colBean.getInsertDefault())?"ng":colBean.getInsertDefault());
						colBean.setControllerDefault(StringUtil.isEmpty(colBean.getControllerDefault())?"ng":colBean.getControllerDefault());
					}
				}
				
				
				// 列名称集合
				if (colComments == null) {
					bean.setColCom("");
					bean.setColComName("");
				} else {
					bean.setColCom(colComments);
					bean.setColComName(colComments.split(":", 0)[0]);
				}
				// 类型 ---目前都转成String类型（预留扩充）
				String type = rs.getString("data_type").toUpperCase();
				bean.setColType(type);
				// 就否允许为空
				bean.setNullFlag(String.valueOf(nullAble));
				// 列大小
				bean.setColSize(String.valueOf(columnSize));
				// 精度
				bean.setDecision(decimalDigits);
				colbeanList.add(bean);
				
				
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return colbeanList;
	}

	/**
	 * 获得一个表的索引信息
	 */
	public void getIndexInfo(String schemaName, String tableName) {
		try {
			ResultSet rs = dbMetaData.getIndexInfo(null, schemaName, tableName,
					true, true);
			while (rs.next()) {
				boolean nonUnique = rs.getBoolean("NON_UNIQUE");// 非唯一索引(Can
																// index values
																// be
																// non-unique.
																// false when
																// TYPE is
																// tableIndexStatistic
																// )
				String indexQualifier = rs.getString("INDEX_QUALIFIER");// 索引目录（可能为空）
				String indexName = rs.getString("INDEX_NAME");// 索引的名称
				short type = rs.getShort("TYPE");// 索引类型
				short ordinalPosition = rs.getShort("ORDINAL_POSITION");// 在索引列顺序号
				String columnName = rs.getString("COLUMN_NAME");// 列名
				String ascOrDesc = rs.getString("ASC_OR_DESC");// 列排序顺序:升序还是降序
				int cardinality = rs.getInt("CARDINALITY"); // 基数
				System.out.println(nonUnique + "-" + indexQualifier + "-"
						+ indexName + "-" + type + "-" + ordinalPosition + "-"
						+ columnName + "-" + ascOrDesc + "-" + cardinality);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获得一个表的主键信息
	 */
	public String getAllPrimaryKeys(String schemaName, String tableName) {
		String columnName = "";
		try {
			ResultSet rs = dbMetaData.getPrimaryKeys(null, schemaName,
					tableName);
			while (rs.next()) {
				columnName = rs.getString("COLUMN_NAME");// 列名
				short keySeq = rs.getShort("KEY_SEQ");// 序列号(主键内值1表示第一列的主键，值2代表主键内的第二列)
				String pkName = rs.getString("PK_NAME"); // 主键名称
				System.out.println(columnName + "-" + keySeq + "-" + pkName);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return columnName;
	}

	/**
	 * 获得一个表的外键信息
	 */
	public void getAllExportedKeys(String schemaName, String tableName) {

		try {
			ResultSet rs = dbMetaData.getExportedKeys(null, schemaName,
					tableName);
			while (rs.next()) {
				String pkTableCat = rs.getString("PKTABLE_CAT");// 主键表的目录（可能为空）
				String pkTableSchem = rs.getString("PKTABLE_SCHEM");// 主键表的架构（可能为空）
				String pkTableName = rs.getString("PKTABLE_NAME");// 主键表名
				String pkColumnName = rs.getString("PKCOLUMN_NAME");// 主键列名
				String fkTableCat = rs.getString("FKTABLE_CAT");// 外键的表的目录（可能为空）出口（可能为null）
				String fkTableSchem = rs.getString("FKTABLE_SCHEM");// 外键表的架构（可能为空）出口（可能为空）
				String fkTableName = rs.getString("FKTABLE_NAME");// 外键表名
				String fkColumnName = rs.getString("FKCOLUMN_NAME"); // 外键列名
				short keySeq = rs.getShort("KEY_SEQ");// 序列号（外键内值1表示第一列的外键，值2代表在第二列的外键）。

				/**
				 * hat happens to foreign key when primary is updated:
				 * importedNoAction - do not allow update of primary key if it
				 * has been imported importedKeyCascade - change imported key to
				 * agree with primary key update importedKeySetNull - change
				 * imported key to NULL if its primary key has been updated
				 * importedKeySetDefault - change imported key to default values
				 * if its primary key has been updated importedKeyRestrict -
				 * same as importedKeyNoAction (for ODBC 2.x compatibility)
				 */
				short updateRule = rs.getShort("UPDATE_RULE");

				/**
				 * What happens to the foreign key when primary is deleted.
				 * importedKeyNoAction - do not allow delete of primary key if
				 * it has been imported importedKeyCascade - delete rows that
				 * import a deleted key importedKeySetNull - change imported key
				 * to NULL if its primary key has been deleted
				 * importedKeyRestrict - same as importedKeyNoAction (for ODBC
				 * 2.x compatibility) importedKeySetDefault - change imported
				 * key to default if its primary key has been deleted
				 */
				short delRule = rs.getShort("DELETE_RULE");
				String fkName = rs.getString("FK_NAME");// 外键的名称（可能为空）
				String pkName = rs.getString("PK_NAME");// 主键的名称（可能为空）

				/**
				 * can the evaluation of foreign key constraints be deferred
				 * until commit importedKeyInitiallyDeferred - see SQL92 for
				 * definition importedKeyInitiallyImmediate - see SQL92 for
				 * definition importedKeyNotDeferrable - see SQL92 for
				 * definition
				 */
				short deferRability = rs.getShort("DEFERRABILITY");
				
				System.out.println(pkTableCat + "-" + pkTableSchem + "-"
						+ pkTableName + "-" + pkColumnName + "-" + fkTableCat
						+ "-" + fkTableSchem + "-" + fkTableName + "-"
						+ fkColumnName + "-" + keySeq + "-" + updateRule + "-"
						+ delRule + "-" + fkName + "-" + pkName + "-"
						+ deferRability);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public void colseCon() {
		try {
			if (con != null) {
				con.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@SuppressWarnings({ "rawtypes", "unchecked", "deprecation" })
	public static void main(String[] args) throws IOException, TemplateException {
		
		CodeBuilder metaData = new CodeBuilder();
		/***************************
		 *  【设置表名】 Enter       *
		 ***************************/
		String tableName="EB_COUPON_GET_RULE";
		
		Configuration cfg = new Configuration();
		cfg.setDirectoryForTemplateLoading(new File("src/main/java/com/solution/common/codegen/ftl"));
		cfg.setObjectWrapper(new DefaultObjectWrapper());
		Template temp = cfg.getTemplate("EntityMapper.xml");
		Map root = new HashMap();
		// 设置表名
		root.put("table", tableName);
		// 设置首字符大写类名  如：CompanyEntity
		String clazz = getClassName(tableName);
		root.put("clazz", clazz);
		// 获取首字符小写短类名  如：company
		String sclazz = getSmallClassName(clazz);
		root.put("sclazz", sclazz);
		// 获取首字符大写短类名  如：Company
		String bclazz = getBmallClassName(clazz);
		root.put("bclazz", bclazz);
		
		// 设置命名空间 和 表注释
		String tableComment = metaData.getTableComment(tableName);
		JSONObject jsonObject = JSONObject.parseObject(tableComment);
		String namespace = jsonObject.getString("namespace");
		String comment = jsonObject.getString("remarks");
		String alias = jsonObject.getString("alias");
		String author = jsonObject.getString("author");
		String webdir = jsonObject.getString("webdir");
		String module = jsonObject.getString("module");
		root.put("namespace", namespace);
		root.put("comment", comment);
		root.put("alias", alias.toUpperCase());
		root.put("author", author);
		root.put("webdir", webdir);
		root.put("module", module);
		
		//root.put("type", config[4]);
		// 查询主键
		String pkName = metaData.getAllPrimaryKeys(null, tableName);
		root.put("pk", pkName);
		root.put("pkProperty", pkName.toLowerCase());
		
		
		// 查询列名集成
		List<ColBean> list =metaData.getTableColumns(null, tableName);
		
		root.put("collist", list);
		
		List<ColBean> condList = new ArrayList<ColBean>();
		if(list!=null && list.size()>0){
			for (ColBean cb : list) {
				if(StringUtil.isNotEmpty(cb.getConditionType())){
					condList.add(cb);
				}
			}
		}
		root.put("condList", condList);

		
		System.out.println("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
		System.out.println("*******************************************************************************************************************************");
		System.out.println("                                        ");
		System.out.println("			"+"您正在生成【"+tableName+"】-【"+comment+"】表对应的代码，");
		System.out.println("");
		System.out.println("			"+"生成代码将会【覆盖！】【覆盖！】【覆盖！】已有代码，确定【毁灭】已有代码打【YES】,取消打【NO】");
		System.out.println("                                        ");
		System.out.println("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
		
		Scanner scan = new Scanner(System.in);
		String read = scan.nextLine();
		if(StringUtil.isEmpty(read)||read.toLowerCase().startsWith("n")){
			System.exit(0);
		}
		
		/**
		 * 生成mybatis映射文件
		 */
		String filePath = "src/main/resources/mybatis/mapper/"+module+"/";
		createNotExistsDir(filePath);
		Writer w = new OutputStreamWriter(new FileOutputStream(filePath+bclazz+"Mapper.xml"));
		temp.process(root, w);
		w.flush();
		
		
		/**
		 * 生成实体类
		 */
		temp = cfg.getTemplate("Entity.ftl");
		String namespaceDir = namespace.replace(".", "/");
		filePath ="src/main/java/"+namespaceDir+"/entity/";
		createNotExistsDir(filePath);
		w = new OutputStreamWriter(new FileOutputStream(
				"src/main/java/"+namespaceDir+"/entity/"+clazz+".java"));
		temp.process(root, w);
		w.flush();

		/**
		 * 生成Service接口
		 */
		temp = cfg.getTemplate("Service.ftl");
		filePath ="src/main/java/"+namespaceDir+"/service/";
		createNotExistsDir(filePath);
		w = new OutputStreamWriter(new FileOutputStream(
				"src/main/java/"+namespaceDir+"/service/"+bclazz+"Service.java"));
		temp.process(root, w);
		w.flush();
		
		/**
		 * 生成ServiceImpl 实现类
		 */
		temp = cfg.getTemplate("ServiceImpl.ftl");
		filePath = "src/main/java/"+namespaceDir+"/service/impl/";
		createNotExistsDir(filePath);
		w = new OutputStreamWriter(new FileOutputStream(
				"src/main/java/"+namespaceDir+"/service/impl/"+bclazz+"ServiceImpl.java"));
		
		temp.process(root, w);
		w.flush();
		
		/**
		 * 生成Dao 接口
		 */
		temp = cfg.getTemplate("Dao.ftl");
		filePath = "src/main/java/"+namespaceDir+"/dao/";
		createNotExistsDir(filePath);
		w = new OutputStreamWriter(new FileOutputStream(
				"src/main/java/"+namespaceDir+"/dao/"+bclazz+"Dao.java"));
		temp.process(root, w);
		w.flush();
		
		/**
		 * 生成DaoImpl实现类
		 */
		temp = cfg.getTemplate("DaoImpl.ftl");
		filePath = "src/main/java/"+namespaceDir+"/dao/impl/";
		createNotExistsDir(filePath);
		w = new OutputStreamWriter(new FileOutputStream(
				"src/main/java/"+namespaceDir+"/dao/impl/"+bclazz+"DaoImpl.java"));
		temp.process(root, w);
		w.flush();
		
		/**
		 * 生成web Controller
		 */
		temp = cfg.getTemplate("Controller.ftl");
		filePath = "src/main/java/"+namespaceDir+"/controller/";
		createNotExistsDir(filePath);
		w = new OutputStreamWriter(new FileOutputStream(
				"src/main/java/"+namespaceDir+"/controller/"+bclazz+"Controller.java"));
		temp.process(root, w);
		w.flush();
		
		
		/**
		 * 生成web 列表页面
		 */
		temp = cfg.getTemplate("page_list.ftl");
		filePath = "src/main/webapp/page/"+webdir+"/";
		createNotExistsDir(filePath);
		w = new OutputStreamWriter(new FileOutputStream(
				"src/main/webapp/page/"+webdir+"/"+sclazz+"_list.jsp"));
		temp.process(root, w);
		w.flush();
		
		/**
		 * 生成web 列表页面 js
		 */
		temp = cfg.getTemplate("js_list.ftl");
		filePath = "src/main/webapp/js/"+webdir+"/";
		createNotExistsDir(filePath);
		w = new OutputStreamWriter(new FileOutputStream(
				"src/main/webapp/js/"+webdir+"/"+sclazz+"_list.js"));
		temp.process(root, w);
		w.flush();
		
		
		
		/**
		 * 生成web 编辑页面
		 */
		temp = cfg.getTemplate("page_form.ftl");
		filePath = "src/main/webapp/page/"+webdir+"/";
		createNotExistsDir(filePath);
		w = new OutputStreamWriter(new FileOutputStream(
				"src/main/webapp/page/"+webdir+"/"+sclazz+"_form.jsp"));
		temp.process(root, w);
		w.flush();
		
		
		/**
		 * 生成web 编辑页面 js
		 */
		temp = cfg.getTemplate("js_form.ftl");
		filePath = "src/main/webapp/js/"+webdir+"/";
		createNotExistsDir(filePath);
		w = new OutputStreamWriter(new FileOutputStream(
				"src/main/webapp/js/"+webdir+"/"+sclazz+"_form.js"));
		temp.process(root, w);
		w.flush();
		
		
		System.out.println("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
		System.out.println();
		System.out.println("	代码生成完成，请【刷新eclipse工程】");
		System.out.println("	把下面两行代码贴到 mybatis-config.xml 中");
		System.out.println();
		System.out.println("	<typeAlias alias=\""+clazz+"\" type=\""+namespace+".entity."+clazz+"\" />");
		System.out.println("	<!--"+comment+" -->");
		System.out.println("	<mapper resource=\"mybatis/mapper/"+module+"/"+bclazz+"Mapper.xml\" />");
		System.out.println();
		System.out.println("	【重启】tomcat");
		System.out.println();
		System.out.println("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
		
		
	}

	
	/**
	 * 创建不存在的文件夹
	 * @param filePath
	 */
	public static void createNotExistsDir(String filePath){
		File dirPath = new File(filePath);
		if(!dirPath.exists()){
			try {
				dirPath.mkdirs();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 获取固定长度的表名（只用于在控制台显示），不够20后补空格
	 * @param tableName
	 * @return
	 */
	public static String getFixLenTableName(String tableName){
		StringBuffer result = new StringBuffer();
		if(tableName.length()<20){
			result.append(tableName);
			for(int i = 0 ; i < 30-tableName.length();i++){
				result.append(" ");
			}
		}
		return result.toString();
	}
	

	public static String proName(String pro) {
		String colName = "";
		String[] arg = (pro.toLowerCase()).split("_", 0);
		for (int i = 0; i < arg.length; i++) {
			if (i == 0) {
				colName = colName + arg[i];
			} else {
				colName = colName + (arg[i].substring(0, 1)).toUpperCase()
						+ arg[i].substring(1);
			}
		}
		return colName;
	}
	
	/**
	 * 表名转类名 如：EB_CUSTOMER  转为 CustomerEntity
	 * @param tableName
	 * @return
	 */
	public static String getClassName(String tableName){
		String clazzName = tableName.toUpperCase().replace("EB_", "").replace("SYS_", "");
		String resultStr = "";
		String[] arg = (clazzName.toLowerCase()).split("_", 0);
		for (int i = 0; i < arg.length; i++) {
			resultStr = resultStr + (arg[i].substring(0, 1)).toUpperCase()
					+ arg[i].substring(1);
		}
		return resultStr+"Entity";
	}
	
	/**
	 * 获取首字符小写短类名  company
	 * @param clazz
	 * @return
	 */
	private static String getSmallClassName(String clazz) {
		return (clazz.substring(0, 1).toLowerCase()
				+ clazz.substring(1)).replace("Entity", "");
	}
	
	/**
	 * 获取首字符大写短类名 如：Compnay
	 * @param clazz
	 * @return
	 */
	private static String getBmallClassName(String clazz) {
		return clazz.replace("Entity", "");
	}

}